#include <ODownloaderTask.h>

ODownloaderTask::ODownloaderTask()
{
	fp=NULL;
	curl_handle=NULL;
	pid=NULL;
	state=e_task_ready;
	pAdditionalProperties=NULL;
	PostData=NULL;
	pthread_mutex_init (&mutex,NULL); 
}

ODownloaderTask::ODownloaderTask(u16 i,string u,string p)
{
	fp=NULL;
	curl_handle=NULL;
	pid=NULL;
	state=e_task_ready;
	ID=i;
	url=u;
	path=p;
	pAdditionalProperties=NULL;
	PostData=NULL;
	pthread_mutex_init (&mutex,NULL); 
}

ODownloaderTask::~ODownloaderTask()
{
	CloseFile();
	if(curl_handle)
		curl_easy_cleanup(curl_handle);
}

void ODownloaderTask::OpenFile()
{
	CloseFile();
	fp=fopen(path.c_str(),"w");
}

void ODownloaderTask::CloseFile()
{
	pthread_mutex_lock (&mutex); 
	if(fp)
		fclose(fp);
	fp=NULL;
	pthread_mutex_unlock(&mutex); 
}

void ODownloaderTask::Start()
{
	curl_handle = curl_easy_init();
	OpenFile();
	state=e_task_downloading;
	pthread_create(&pid,NULL,DoDownLoad,this);
}

void ODownloaderTask::Stop()
{
	state=e_task_userstop;
	pthread_cancel(pid);
	pthread_join(pid,NULL);
	pid=NULL;
	ClearProperties();
	PostData=NULL;
	curl_easy_cleanup(curl_handle);
	curl_handle = NULL;
	CloseFile();
}

void ODownloaderTask::Pause()
{
	if(!(state==e_task_userstop||state==e_task_completed)){
		if(state==e_task_downloading)
			state=e_task_paused;
		else
			state=e_task_downloading;
		curl_easy_pause(curl_handle, CURLPAUSE_ALL);
	}
}

void ODownloaderTask::SetID(int i)
{
	ID=i;
}

void ODownloaderTask::SetUrl(string u)
{
	url=u;
}

void ODownloaderTask::SetPath(string p)
{
	path=p;
}

ODownloaderTask::e_taskstate ODownloaderTask::GetTaskState()
{
	return state;
}

u16 ODownloaderTask::GetID()
{
	return ID;
}

const char *ODownloaderTask::GetUrl()
{
	return url.c_str();
}

const char *ODownloaderTask::GetPath()
{
	return path.c_str();
}

double ODownloaderTask::GetDownloadSpeed()
{
	double dSpeed=0;
	if(state==e_task_downloading)
		curl_easy_getinfo(curl_handle, CURLINFO_SPEED_DOWNLOAD, &dSpeed);
	return dSpeed;
}

double ODownloaderTask::GetUploadSpeed()
{
	double uSpeed=0;
	if(state==e_task_downloading)
		curl_easy_getinfo(curl_handle, CURLINFO_SPEED_UPLOAD, &uSpeed);
	return uSpeed;
}

double ODownloaderTask::GetFileSize()
{
	double filesize=0;
	if(state==e_task_downloading)
		curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &filesize );
	return filesize;
}

double ODownloaderTask::GetDownloadSize()
{
	double downloadsize=0;
	if(state==e_task_downloading)
		curl_easy_getinfo(curl_handle, CURLINFO_SIZE_DOWNLOAD, &downloadsize );
	return downloadsize;
}

double ODownloaderTask::GetDownloadProgress()
{
	if(state==e_task_downloading)
		return GetDownloadSize()/GetFileSize();
	return 0;
}

void ODownloaderTask::Completed()
{
	state=e_task_completed;
	pthread_join(pid,NULL);
	pid=NULL;
	CloseFile();
	ClearProperties();
	PostData=NULL;
	system("sync");
}

void ODownloaderTask::AddProperties(char *p)
{
	pAdditionalProperties=curl_slist_append(pAdditionalProperties,p);
}

void ODownloaderTask::ClearProperties()
{
	curl_slist_free_all(pAdditionalProperties);
	pAdditionalProperties=NULL;
}

void ODownloaderTask::SetPostData(char *data)
{
	PostData=data;
}

void *ODownloaderTask::DoDownLoad(void * a)
{
	ODownloaderTask *task=(ODownloaderTask *)a;

	curl_easy_setopt(task->curl_handle, CURLOPT_URL, task->url.c_str());
	curl_easy_setopt(task->curl_handle, CURLOPT_WRITEFUNCTION, DownLoadWriteFile);
	curl_easy_setopt(task->curl_handle, CURLOPT_WRITEDATA, (void *)(task->fp));
	curl_easy_setopt(task->curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
	if(task->pAdditionalProperties){
			curl_easy_setopt(task->curl_handle, CURLOPT_POST, 1);
			curl_easy_setopt(task->curl_handle, CURLOPT_POSTFIELDS, task->PostData);
			curl_easy_setopt(task->curl_handle, CURLOPT_HTTPHEADER, task->pAdditionalProperties);
	}

	curl_easy_perform(task->curl_handle);
	DBG_INFO("LUUU  %s  downloaded!!\n",task->path.c_str());
	task->Completed();
	curl_easy_cleanup(task->curl_handle);
	task->curl_handle = NULL;
	DBG_INFO("over\n");
	return NULL;
}

size_t ODownloaderTask::DownLoadWriteFile(void *buffer, size_t size, size_t nmemb, void *user_p)
{
	FILE *fpp = (FILE *)user_p;
	return fwrite(buffer, size, nmemb, fpp);
}
